﻿using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
using Furion.DatabaseAccessor;
using Furion.FriendlyException;
using Mapster;
using SqlSugar;
using System.ComponentModel;
using HiSportApplet.Application.Common.SqlSugar;
using HiSportApplet.Core.Entity.Bas;
using HiSportApplet.Application.Service.Bas.BasVenuesManagement.Dtos;
using HiSportApplet.Core.Util;
using Furion.LinqBuilder;
using HiSportApplet.Core.Entity.Sys;
using System.Text;
using NewLife.Reflection;
using Furion.ClayObject.Extensions;
using System.Collections.Generic;

namespace HiSportApplet.Application.Service.Bas.BasVenuesManagement
{

    /// <summary>
    /// 场馆
    /// </summary>
    [ApiDescriptionSettings("基础资料", Tag = "场馆", SplitCamelCase = false)]
    public class BasVenuesService : ITransient, IBasVenuesService, IDynamicApiController
    {
        private readonly SqlSugarRepository<BasVenues> _basVenuesRep;
        private readonly SqlSugarRepository<BasVenuesImage> _imageRep;
        private readonly SqlSugarRepository<BasVenueTag> _basVenueTag;
        private readonly SqlSugarRepository<SysVenuesTag> _sysTagRep;
        private readonly ISqlSugarClient _ISqlSugarClient;
        private readonly SqlSugarRepository<BasVenuesEventsType> _basVenuesEventsTypeRep;
        private readonly SqlSugarRepository<BasSportsEventsType> _sportEventsTypeRep;
        private readonly SqlSugarRepository<BasSite> _basSiteRep;
        private readonly SqlSugarRepository<BasSiteType> _basSiteTypeRep;

        /// <summary>
        /// 场馆的浏览量
        /// </summary>
        private readonly SqlSugarRepository<BasVenueViews> _basVenueViewsRep;
        /// <summary>
        /// 场馆的预定量
        /// </summary>
        private readonly SqlSugarRepository<BasVenueBook> _basVenueBookRep;


        public BasVenuesService(
            SqlSugarRepository<BasVenues> basVenuesRep,
            SqlSugarRepository<BasVenuesImage> imageRep,
            SqlSugarRepository<BasVenueTag> basVenueTag,
            SqlSugarRepository<SysVenuesTag> sysTagRep,
            ISqlSugarClient ISqlSugarClient,
            SqlSugarRepository<BasVenueViews> basVenueViewsRep,
            SqlSugarRepository<BasVenueBook> basVenueBookRep,
            SqlSugarRepository<BasVenuesEventsType> basVenuesEventsTypeRep,
            SqlSugarRepository<BasSportsEventsType> sportEventsTypeRep,
            SqlSugarRepository<BasSite> basSiteRep,
            SqlSugarRepository<BasSiteType> basSiteTypeRep

            )
        {
            _basVenuesRep = basVenuesRep;
            _imageRep = imageRep;
            _basVenueTag = basVenueTag;
            _sysTagRep = sysTagRep;
            _ISqlSugarClient = ISqlSugarClient;
            _basVenueViewsRep = basVenueViewsRep;
            _basVenueBookRep = basVenueBookRep;
            _basVenuesEventsTypeRep = basVenuesEventsTypeRep;
            _sportEventsTypeRep = sportEventsTypeRep;
            _basSiteRep = basSiteRep;
            _basSiteTypeRep = basSiteTypeRep;
        }

        /// <summary>
        /// 查询场馆列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>       
        [ApiDescriptionSettings(Name = "SearchVenuesList"), HttpPost]
        [DisplayName("查询场馆列表")]
        public async Task<SqlSugarPagedList<BasVenuesBasicDto>> SearchVenuesList(BasVenuesInputDto input)
        {
            ParamNull(input);
            var data = SqlWhereSql(input);
            if (data == null) return new SqlSugarPagedList<BasVenuesBasicDto>();

            #region  排序方式
            #region TODO：按照什么规则进行排序
            var orderType = input.OrderType;
            if (orderType == 1)
            {
                if (input.Longitude == null || !input.Longitude.HasValue)
                {
                    throw Oops.Oh("需要定位当前位置");

                }
                if (input.Latitude == null || !input.Latitude.HasValue)
                {
                    throw Oops.Oh("需要定位当前位置");

                }
                data = data.Where(a => !string.IsNullOrWhiteSpace(a.Longitude) && !string.IsNullOrWhiteSpace(a.Latitude));

                data = data.OrderBy(a => a.Distinct);
            }
            #endregion

            //TODO:按照距离从近到远

            //TODO:综合排序等

            var result = await data.Select(x => new BasVenuesBasicDto { Id = x.Id.SelectAll() }).ToPagedListAsync(input.Page, input.PageSize);

            #endregion


            #region 返回结果

            var curPageData = result.Items.ToList();
            if (curPageData.Count() <= 0) return result;
            var ids = curPageData.Select(a => a.Id).ToList();
            #endregion

            //场馆的图片
            var imageData = _imageRep.AsQueryable().Where(a => ids.Contains(a.VenuesId)).Select(a => new { a.VenuesId, a.Image }).ToList();


            #region 场馆预定人数

            var venumOrderData = new List<BasVenueBook>();
            if (input.IsSearchBook)
            {
                venumOrderData = _basVenueBookRep.AsQueryable()
               .Where(a => ids.Contains(a.VenuesId))
               .ToList();
            }

            #endregion

            #region 场馆浏览人数
            var venumViewData = new List<BasVenueViews>();
            if (input.IsSearchView)
            {
                venumViewData = _basVenueViewsRep.AsQueryable()
               .Where(a => ids.Contains(a.VenuesId))
               .ToList();
            }
            #endregion


            #region 场馆标签

            var venueTags = _basVenueTag.AsQueryable()
                .InnerJoin<SysVenuesTag>((a, b) => a.SysVenueTagId == b.Id)
                .Where(a => ids.Contains(a.VenuesId))
                .Select((a, b) => new { a.VenuesId, a.SysVenueTagId, b.TagName })
                .ToList();

            #endregion

            foreach (var item in curPageData)
            {
                var venuesId = item.Id;

                //场馆图片
                var imageList = imageData.Where(a => a.VenuesId == venuesId).Select(a => a.Image).ToList();
                item.ImageList = imageList;

                //场馆标签
                var tagNames = venueTags.Where(a => a.VenuesId == venuesId).Select(a => a.TagName).ToList();
                item.ImageList = imageList;

                //预订人数
                var orderData = venumOrderData.FirstOrDefault(a => a.VenuesId == venuesId);
                item.OrderQty = orderData == null ? 0 : orderData.Qty;

                //浏览次数
                var viewData = venumViewData.FirstOrDefault(a => a.VenuesId == venuesId);
                item.ViewQty = viewData == null ? 0 : viewData.Qty;

                //营业状态-是否需要前段自动更新
                var startTime = item.TimeStart;
                var endTime = item.TimeEnd;

            }
            return result;
        }

        /// <summary>
        /// 查询某个球馆有的运动类型
        /// </summary>
        /// <returns></returns>
        [ApiDescriptionSettings(Name = "SearchVenuesEventsType"), HttpPost]
        [DisplayName("查询某个场馆包含的运动项目类型")]
        public List<SearchVenuesEventsTypeOutputDto> SearchVenuesEventsType(SearchVenuesEventsTypeInputDto input)
        {
            ParamNull(input);

            var venuesSiteTypeIds = _basSiteRep.AsQueryable().Where(a => a.VenuesId == input.VenuesId).Select(a => a.SiteTypeId).Distinct().ToList();

            var venueTags = _basSiteTypeRep.AsQueryable()
                .InnerJoin<BasSportsEventsType>((a, b) => a.SportsEventsTypeCode == b.SportsEventsCode)
                .Where(a => a.IsDelete == false && venuesSiteTypeIds.Contains(a.Id))
                .OrderBy(a => a.Seq)
                .Select((a, b) => new SearchVenuesEventsTypeOutputDto
                {
                    VenuesId = input.VenuesId,
                    SportsEventsName = b.SportsEventsName,
                    SportsEventsCode = b.SportsEventsCode,
                    SiteTypeName = a.SiteTypeName,
                    SiteTypeId = a.Id,
                    Icon = b.Icon,
                    Status = b.Status
                })
                .ToList();
            return venueTags;
        }



        /// <summary>
        /// 根据ID查询具体场馆信息
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [ApiDescriptionSettings(Name = "viewBasVenues"), HttpPost]
        [DisplayName("查询单个场馆")]
        public async Task<BasVenuesBasicDto> viewBasVenues(BasVenuesSqlDto param)
        {
            var data = await GetBasVenues(param.Id);
            //场馆的图片
            var imageData = _imageRep.AsQueryable().Where(a => data.Id == a.VenuesId).Select(a => a.ImageUrl).ToList();
            var result = data.Adapt<BasVenuesBasicDto>();
            result.ImageList = imageData;
            try
            {
                var inputLatitudeRad = DegreesToRadians(Convert.ToDouble(param.Latitude));
                var inputLongitudeRad = DegreesToRadians(Convert.ToDouble(param.Longitude));
                var venuseLatitude = DegreesToRadians(Convert.ToDouble(data.Latitude));
                var venuseLongitude = DegreesToRadians(Convert.ToDouble(data.Longitude));

                // 经纬度差值
                var dLat = inputLatitudeRad - venuseLatitude;
                var dLon = inputLongitudeRad - venuseLongitude;

                var a = Math.Pow(Math.Sin(dLat / 2), 2) +
               Math.Cos(venuseLatitude) * Math.Cos(inputLatitudeRad) *
               Math.Pow(Math.Sin(dLon / 2), 2);
                var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
                result.Distance = (decimal?)(6371.0 * c);
            }
            catch (Exception)
            {

            }
            return result;
        }
        // PostCustomer
        //weixin    MiniProgramCrm/MiniLogin
        #region 其余私有方法


        private static double DegreesToRadians(double degrees)
        {
            return degrees * Math.PI / 180.0;
        }

        /// <summary>
        /// 查询单个场馆信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private async Task<BasVenues> GetBasVenues(long id)
        {

            var data = await _basVenuesRep.GetFirstAsync(a => a.Id == id && a.IsDelete == false);
            if (data == null) throw Oops.Oh("未查询到当前场馆信息");
            return data;
        }




        /// <summary>
        /// 查询列表Where条件拼装
        /// 要验证返回NULL的情况
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private ISugarQueryable<BasVenues> SqlWhere(BasVenuesInputDto input)
        {

            ParamNull(input);


            ISugarQueryable<BasVenues> data;
            #region 附近N千米
            var distance = input.Distance;
            if (distance != null && distance.HasValue && distance.Value > 0)
            {

                if (input.Longitude == null || !input.Longitude.HasValue)
                {
                    throw Oops.Oh("需要定位当前位置");

                }
                if (input.Latitude == null || !input.Latitude.HasValue)
                {
                    throw Oops.Oh("需要定位当前位置");

                }
                //附近N千米

                var sql = $@"	
SELECT
*
FROM
	BasVenues 
WHERE
	(
		6371 * ACOS(
			COS(
				RADIANS({input.Latitude} )) * COS(
				RADIANS( {input.Longitude} )) * COS(
				RADIANS( longitude ) - RADIANS( 104.071604 )) + SIN(
				RADIANS( 30.553377 )) * SIN(
			RADIANS( latitude )) 
		) 
	)<={distance};
		";
                var db = _ISqlSugarClient;
                data = db.SqlQueryable<BasVenues>(sql);


                //TODO:
                //                SELECT
                //id, name, latitude, longitude,
                //(
                //    6371 * ACOS(
                //       COS(RADIANS(target_latitude)) *
                //       COS(RADIANS(latitude)) *
                //       COS(RADIANS(longitude) - RADIANS(target_longitude)) +
                //       SIN(RADIANS(target_latitude)) * SIN(RADIANS(latitude))
                //   )
                //) AS distance
                //FROM
                //your_table
                //ORDER BY
                //distance;

            }
            else
            {
                data = _basVenuesRep.AsQueryable();
            }
            #endregion





            data = data.Where(a => a.IsDelete == false && a.Status == 1);

            #region 省份
            var province = input.Province;
            if (!string.IsNullOrWhiteSpace(province))
            {
                data = data.Where(a => a.Province == province);
            }
            #endregion

            #region 市
            var city = input.City;
            if (!string.IsNullOrWhiteSpace(city))
            {
                data = data.Where(a => a.City == city);
            }
            #endregion

            #region 区
            var area = input.Area;
            if (!string.IsNullOrWhiteSpace(area))
            {
                data = data.Where(a => a.Area == area);
            }
            #endregion

            #region 场馆名称-模糊查询
            var venuesName = input.VenuesName;
            if (!string.IsNullOrWhiteSpace(venuesName))
            {
                data = data.Where(a => a.VenuesName.Contains(venuesName));
            }
            #endregion

            #region 运动类型Code
            var sportsEventsTypeCodeList = input.SportsEventsTypeCodeList;
            if (!sportsEventsTypeCodeList.IsNullOrEmpty() && sportsEventsTypeCodeList.Any())
            {

                data = data.Where(a => SqlFunc.Subqueryable<BasVenuesEventsType>().Where(b => b.IsDelete == false && b.VenuesId == a.Id && sportsEventsTypeCodeList.Contains(b.SportsEventsTypeCode)).Any());

            }
            #endregion


            #region 状态
            var status = input.Status;
            if (status != null && status.HasValue && status.Value > 0)
            {
                data = data.Where(a => a.Status == status.Value);
            }
            #endregion



            return data;
        }

        /// <summary>
        /// 查询列表Where条件拼装
        /// 要验证返回NULL的情况
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private ISugarQueryable<BasVenuesSqlDto> SqlWhereSql(BasVenuesInputDto input)
        {


            ParamNull(input);
            /*纯Sql语句查询*/

            var whereSql = new StringBuilder();

            #region 附近N千米
            var distance = input.Distance;
            if (distance != null && distance.HasValue && distance.Value > 0)
            {

                if (input.Longitude == null || !input.Longitude.HasValue)
                {
                    throw Oops.Oh("需要定位当前位置");

                }
                if (input.Latitude == null || !input.Latitude.HasValue)
                {
                    throw Oops.Oh("需要定位当前位置");

                }

                whereSql.AppendLine(@$" 	AND Distance <= {distance}");
            }
            #endregion

            #region 省份
            var province = input.Province;
            if (!string.IsNullOrWhiteSpace(province))
            {
                whereSql.AppendLine(@$" AND Province ='{province}'");
            }
            #endregion

            #region 市
            var city = input.City;
            if (!string.IsNullOrWhiteSpace(city))
            {
                whereSql.AppendLine(@$" AND City ='{city}'");
                // data = data.Where(a => a.City == city);
            }
            #endregion

            #region 区
            var area = input.Area;
            if (!string.IsNullOrWhiteSpace(area))
            {
                whereSql.AppendLine(@$" AND Area ='{area}'");

                //data = data.Where(a => a.Area == area);
            }
            #endregion

            #region 场馆名称-模糊查询
            var venuesName = input.VenuesName;
            if (!string.IsNullOrWhiteSpace(venuesName))
            {
                whereSql.AppendLine(@$" AND VenuesName like  '%{venuesName}%'");
                // data = data.Where(a => a.VenuesName.Contains(venuesName));
            }
            #endregion

            #region 状态
            var status = input.Status;
            if (status != null && status.HasValue && status.Value > 0)
            {
                whereSql.AppendLine(@$" AND Status ='{status.Value}'");
                // data = data.Where(a => a.Status == status.Value);
            }
            #endregion

            #region 运动类型Code
            var sportsEventsTypeCodeList = input.SportsEventsTypeCodeList;
            if (!sportsEventsTypeCodeList.IsNullOrEmpty() && sportsEventsTypeCodeList.Any())
            {

                //foreach (var item in sportsEventsTypeCodeList)
                //{
                //    item = $"'{item}'";
                //}

                var str = string.Join(',', sportsEventsTypeCodeList);

                whereSql.AppendLine(@$" AND EXISTS(SELECT* FROM BasVenuesEventsType WHERE IsDelete = FALSE AND SportsEventsTypeCode in ({str}) AND BasVenuesEventsType.VenuesId = t_temp.Id)");


            }
            #endregion


            var sql = new StringBuilder();
            sql.Append($@"SELECT
	* 
FROM
	(
	SELECT
		*,
		(
			6371 * ACOS(
				COS(
					RADIANS( {input.Latitude}  )) * COS(
					RADIANS( latitude )) * COS(
					RADIANS( longitude ) - RADIANS( {input.Longitude} )) + SIN(
					RADIANS( {input.Latitude}  )) * SIN(
				RADIANS( latitude )) 
			) 
		) AS Distance 
	FROM
		BasVenues 
	WHERE
		IsDelete = FALSE 
	) AS t_temp 
WHERE
	IsDelete = FALSE 
	{whereSql.ToString()} ");
            //末尾不能加任何的分号  框架下面会再一次拼接语句 导致异常

            var sqlResult = sql.ToString();
            var db = _ISqlSugarClient;
            var data = db.SqlQueryable<BasVenuesSqlDto>(sqlResult);
            return data;
        }

        /// <summary>
        /// 参数为NULL验证
        /// </summary>
        /// <param name="input"></param>
        private void ParamNull(object input)
        {
            if (input == null) throw Oops.Oh("参数错误:参数为NULL");
        }

        #endregion

    }




}
